<template>
  <div style="width: 100%">
    <div class="info-driver">
      <span class="ws-status">
      服务连接状态：<el-icon v-if="wsStatus" color="#2E5CF6" :size="18">
      <CircleCheckFilled/>
    </el-icon>
      <el-icon v-else class="" color="#ff0000" :size="18">
         <CircleCloseFilled/>
      </el-icon>
    </span>

      <span class="ws-status">
      设备编码：{{driverCode}}
    </span>

    </div>

  </div>
</template>
<script setup lang="ts" name="global-websocket">
import {ElMessage} from 'element-plus';

const emit = defineEmits(['rollback']);

const state = reactive({
  webSocket: ref(), // webSocket实例
  lockReconnect: false, // 重连锁，避免多次重连
  maxReconnect: -1, // 最大重连次数， -1 标识无限重连
  reconnectTime: 0, // 重连尝试次数
  heartbeat: {
    interval: 30 * 1000, // 心跳间隔时间
    timeout: 10 * 1000, // 响应超时时间
    pingTimeoutObj: ref(), // 延时发送心跳的定时器
    pongTimeoutObj: ref(), // 接收心跳响应的定时器
    pingMessage: JSON.stringify({type: "HEARTBEAT"}), // 心跳请求信息
  },
});
const driverCode = ref(null)
const wsStatus = ref(false)


// onMounted(() => {
//   initWebSocket();
// });

onUnmounted(() => {
  state.webSocket.close();
  clearTimeoutObj(state.heartbeat);
});


const setCode = (code: any) => {
  driverCode.value = code;
  initWebSocket();
}

const initWebSocket = () => {
  if (driverCode.value === null || driverCode.value === '') {
    ElMessage({
      message: '未获取到code',
      type: 'warning',
      duration: 0
    })
    return;
  }

  // ws地址
  // let host = window.location.host;
  let wsUri = `ws://${window.location.host}/ws/${driverCode.value}`;
  // 建立连接
  state.webSocket = new WebSocket(wsUri);
  // 连接成功
  state.webSocket.onopen = onOpen;
  // 连接错误
  state.webSocket.onerror = onError;
  // 接收信息
  state.webSocket.onmessage = onMessage;
  // 连接关闭
  state.webSocket.onclose = onClose;
};

const reconnect = () => {
  if (state.lockReconnect || (state.maxReconnect !== -1 && state.reconnectTime > state.maxReconnect)) {
    return;
  }
  state.lockReconnect = true;
  setTimeout(() => {
    state.reconnectTime++;
    // 建立新连接
    initWebSocket();
    state.lockReconnect = false;
  }, 5000);
};
/**
 * 清空定时器
 */
const clearTimeoutObj = (heartbeat: any) => {
  heartbeat.pingTimeoutObj && clearTimeout(heartbeat.pingTimeoutObj);
  heartbeat.pongTimeoutObj && clearTimeout(heartbeat.pongTimeoutObj);
};
/**
 * 开启心跳
 */
const startHeartbeat = () => {
  const webSocket = state.webSocket;
  const heartbeat = state.heartbeat;
  // 清空定时器
  clearTimeoutObj(heartbeat);
  // 延时发送下一次心跳
  heartbeat.pingTimeoutObj = setTimeout(() => {
    // 如果连接正常
    if (webSocket.readyState === 1) {
      //这里发送一个心跳，后端收到后，返回一个心跳消息，
      webSocket.send(heartbeat.pingMessage);
      // 心跳发送后，如果服务器超时未响应则断开，如果响应了会被重置心跳定时器
      heartbeat.pongTimeoutObj = setTimeout(() => {
        webSocket.close();
      }, heartbeat.timeout);
    } else {
      // 否则重连
      reconnect();
    }
  }, heartbeat.interval);
};

/**
 * 连接成功事件
 */
const onOpen = () => {
  //开启心跳
  wsStatus.value = true
  startHeartbeat();
  state.reconnectTime = 0;
};
/**
 * 连接失败事件
 * @param e
 */
const onError = () => {
  //重连
  wsStatus.value = false
  reconnect();
};

/**
 * 连接关闭事件
 * @param e
 */
const onClose = () => {
  //重连
  // reconnect();
  wsStatus.value = false
};
/**
 * 接收服务器推送的信息
 * @param event
 */
const onMessage = (event: any) => {
  //收到服务器信息，心跳重置并发送
  startHeartbeat();
  if (event.data !== "") {
    const data = JSON.parse(event.data);
    if (
        data.code === 0 &&
        (data.data === "pong" || data.data === "登陆成功")
    )
      return;

    if (
        data.code === 1 &&
        (data.msg === "该设备连接已存在" || data.msg === "未找到该设备编码")
    ) {
      ElMessage({
        message: data.msg,
        type: 'warning',
        duration: 3000
      })
      return;
    }
    emit('rollback', data);
  }
  // const text = msgEvent.data;
  // const msg = msgEvent.msg;
  // if (text.indexOf('pong') > 0 || text.indexOf('登陆成功') > 0) {
  //   return;
  // }
  //
  // if ()

  // ElNotification.warning({
  //   title: '消息提醒',
  //   dangerouslyUseHTMLString: true,
  //   message: text + '请及时处理',
  //   offset: 60,
  // });
};


defineExpose({
  setCode
})
</script>
<style scoped lang="scss">
.info-driver{
  display: flex;
  justify-content: space-between;
  width: 100%;

}
.ws-status {
  display: flex;
  align-items: center;
  font-size: 16px;
  line-height: 1.5;
}
</style>
